package com.carleasoft.mps.forum.install;

import cn.hutool.core.util.ReUtil;
import com.carleasoft.mps.data.redis.JedisService;
import com.carleasoft.mps.data.redis.base.CacheKeyEnum;
import com.carleasoft.mps.forum.annotation.OpenApi;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;


/**
 * @author zang
 * @desc 启动的时候添加访问白名单
 * @date 2022-07-26
 */
@Slf4j
@Configuration
@RequiredArgsConstructor
public class InstallOpenApi implements InitializingBean, Ordered {


    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");

    private final WebApplicationContext applicationContext;

    @Value("${spring.application.name}")
    private String serverName;
    @Autowired
    private JedisService jedisService;

    @Getter
    @Setter
    private Set<String> ignoreUrls = new HashSet<>();


    @Override
    public void afterPropertiesSet() {
        // 项目服务路径
        String contextPath = applicationContext.getServletContext().getContextPath();

        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> requestHandlerMap = mapping.getHandlerMethods();

        requestHandlerMap.entrySet().forEach(entry -> {

            RequestMappingInfo requestInfo = entry.getKey();
            HandlerMethod handlerMethod = entry.getValue();

            // 获取类上边的注解,
            OpenApi clazzOpen = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), OpenApi.class);
            Optional.ofNullable(clazzOpen)
                    .ifPresent(inner -> requestInfo.getPatternsCondition().getPatterns()
                            .forEach(url -> ignoreUrls.add(contextPath + ReUtil.replaceAll(url, PATTERN, "*"))));


            // 获取方法上边的注解
            OpenApi methodInner = handlerMethod.getMethod().getAnnotation(OpenApi.class);
            Optional.ofNullable(methodInner)
                    .ifPresent(inner -> {
                        // 添加放行的Method
                        Set<String> patterns = requestInfo.getPatternsCondition().getPatterns();
                        // Set<RequestMethod> methods = requestInfo.getMethodsCondition().getMethods();
                        String url = (String) patterns.toArray()[0];
                        // 添加了 Inner 注解的方法方法Url
                        ignoreUrls.add(contextPath + ReUtil.replaceAll(url, PATTERN, "*"));
                    });

        });
        // 白名单填入库
        this.whiteListIntoRedis();
    }
    /**
     * 白名单添加到Redis
     */
    private void whiteListIntoRedis()  {
        String witheKey = serverName + "_WITHE_API";
        jedisService.deleteObject(CacheKeyEnum.PREFIX_WITHE_API,witheKey);
        for (String s : ignoreUrls) {
            System.out.println(s);
        }
        jedisService.addObject(CacheKeyEnum.PREFIX_WITHE_API,witheKey,ignoreUrls);
        System.out.println(jedisService.getObject(CacheKeyEnum.PREFIX_WITHE_API,witheKey));
    }
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}
